import { UploadService } from './../../../../../services/upload.service';
import { EventManagerService } from './../../../../../services/event-manager.service';
import { BaseService } from './../../../../../services/base.service';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Subscription } from 'rxjs';
import { ComponentValidation, DataRegister, ValidationType } from 'src/app/models';
import { ComponentInnerEvent, PermitConfig, ZeprideAuthorityData } from '../../../models';
import { EngineComponent } from '../../../models/engine-component';
import { EngineService } from '../../../services/engine.service';
import { OrganizationService } from 'src/app/services/organization.service';
import { NzMessageService } from 'ng-zorro-antd';
import { DataRegisterService } from 'src/app/services';

@Component({
  selector: 'zepride-base-field',
  template: ''
})
export class BaseFieldComponent {
  /**
   * 组件绑定的数据模型
   */
  get dataModel() {
    return this.engineService.currentDataModel;
  }

  get mapDataModel() {
    return this.engineService.mapDataModel;
  }

  /**
   * 获取指定的值，如果组件没有绑定字段则返回默认值
   */
  get bindData() {
    const bindField = this.componentData.bindField;
    if (bindField) {
      return this.dataModel[bindField];
    } else {
      return this.componentData.defaultValue;
    }
  }

  get mapBindData() {
    const bindField: string[] = this.componentData.extends.mapField;
    if (bindField) {
      return this.mapDataModel[bindField[0]][bindField[1]];
    }

    return null;
  }

  get dataChangeLog(): { time: number; sourceValue, targetValue } {
    if (this.dataModel && this.dataModel.dataChangeLog) {
      const changeLog = this.dataModel.dataChangeLog;
      if (!changeLog.data[this.componentData.bindField]) {
        return null;
      }
      const changeLogData = changeLog.data[this.componentData.bindField];

      return {
        time: changeLogData.updateTime ? changeLogData.updateTime : this.dataModel.dataChangeLog.updateTime,
        sourceValue: changeLogData.sourceValue,
        targetValue: changeLogData.targetValue
      };
    }
    return null;
  }

  constructor(
    protected engineService: EngineService,
    protected baseSvr: BaseService,
    protected eventSvr: EventManagerService,
    protected orgSvr: OrganizationService,
    public uploadService: UploadService,
    protected msg: NzMessageService,
    protected dataRegisterService: DataRegisterService
  ) { }

  @Input() tmpComItemId: string;
  /**
   * 定义组件的数据
   */
  @Input() componentData: EngineComponent;
  /**
   * 组件内部通知的事件
   */
  @Output() innerEvent: EventEmitter<ComponentInnerEvent> = new EventEmitter<ComponentInnerEvent>();
  /**
   * 组件的值发生变化时的通知
   */
  modelChange$: Subscription;
  /**
   * 组件的权限配置
   */
  permitConfig: PermitConfig[] = [];
  /**
   * 组件的权限数据
   */
  zeprideAuthorityData: ZeprideAuthorityData;
  dataRegister: DataRegister;
  /**
   * 验证字段的方法
   */
  validatorFns = {
    required: (currentValue: any) => {
      const result = currentValue === '' || currentValue == null || currentValue === undefined;
      if (result) {
        return { required: true };
      } else {
        return null;
      }
    },
    pattern: (currentValue: any, validation?: ComponentValidation) => {
      const regExp = new RegExp(validation.value);
      const result = regExp.test(currentValue);
      if (result) {
        return null;
      } else {
        return { pattern: true };
      }
    },
    max: (currentValue: any, validation?: ComponentValidation) => {
      const isNotNumber = isNaN(currentValue);
      const result = !isNotNumber && Number(currentValue) <= Number(validation.value);
      if (result) {
        return null;
      } else {
        return { max: true };
      }
    },
    min: (currentValue: any, validation?: ComponentValidation) => {
      const isNotNumber = isNaN(currentValue);
      const result = !isNotNumber && Number(currentValue) >= Number(validation.value);
      if (result) {
        return null;
      } else {
        return { min: true };
      }
    },
    maxLength: (currentValue: any, validation?: ComponentValidation) => {
      const length = currentValue.length ? currentValue.length : 0;
      const result = length <= validation.value;
      if (result) {
        return null;
      } else {
        return { maxLength: true };
      }
    },
    minLength: (currentValue: any, validation?: ComponentValidation) => {
      const length = currentValue.length ? currentValue.length : 0;
      const result = length >= validation.value;
      if (result) {
        return null;
      } else {
        return { minLength: true };
      }
    },
    unique: async (params?: {
      objectId?: string;
      dataType: string;
      field: string;
    }) => {
      if (!params || !params.dataType) {
        return null;
      }
      const data = await this.dataRegisterService.getComponentData(params);
      if (data && data.list && data.list.length) {
        return Promise.resolve({ unique: true });
      } else {
        return null;
      }
    }
  };

  expandedValidation: () => void;

  /**
   * 页面保存触发的事件
   *
   */
  pageSavedHandle: () => Promise<any>;
  /**
   * 获取验证规则的目标值
   * @param type 验证规则的类型
   */
  getValidationValue(type: ValidationType) {
    const validations = this.componentData.validations;
    const data = validations.find(item => item.type === type);
    return data && data.value;
  }
  /**
   * 验证之后的错误提示信息
   * @param identifyId 组件的uuid
   */
  getErrorMsg(identifyId: string) {
    if (!this.engineService.fieldErrors || !this.engineService.fieldErrors.length) {
      return;
    }
    const fieldError = this.engineService.fieldErrors.find(error => error.identifyId === identifyId);
    if (!fieldError) {
      return;
    }
    const keys = Object.keys(fieldError.errors);
    if (!keys || !keys.length) {
      return;
    }
    const type = keys[0];
    let msg = '';
    switch (type) {
      case 'required':
        msg = `请填写${fieldError.name}`;
        break;
      case 'pattern':
        msg = '数据格式不正确';
        break;
      case 'max':
        const maxValue = this.getValidationValue('max');
        msg = `最大值为【${maxValue}】`;
        break;
      case 'min':
        const minValue = this.getValidationValue('min');
        msg = `最小值为【${minValue}】`;
        break;
      case 'minLength':
        const minLengthValue = this.getValidationValue('minLength');
        msg = `最小长度为【${minLengthValue}】`;
        break;
      case 'maxLength':
        const maxLengthValue = this.getValidationValue('maxLength');
        msg = `最大长度为【${maxLengthValue}】`;
        break;
      case 'unique':
        msg = `已存在值【${fieldError.value}】`;
        break;
    }
    return msg;
  }
  /**
   * 设置绑定字段的值
   * @param value 新的值
   */
  setBindData(value: any) {
    const bindField = this.componentData.bindField;
    if (bindField) {
      this.formatObj(value, bindField);
      this.setMapBindData(value);
      this.onDataModelChange(bindField, value);
      this.componentData.defaultValue = value;
    } else {
      this.componentData.defaultValue = value;
    }
  }

  onDataModelChange(bindField, value) {
    this.engineService.dataModelChange$.next({
      bindField,
      value,
      identifyId: this.componentData.identifyId,
      tmpComItemId: this.tmpComItemId,
      dataModel: this.dataModel,
      selector: this.componentData.selector
    });
  }

  setData(value: any) {
    const bindField = this.componentData.bindField;
    if (bindField) {
      this.formatObj(value, bindField);
      this.setMapBindData(value);
      this.componentData.defaultValue = value;
    } else {
      this.componentData.defaultValue = value;
    }
  }

  setMapBindData(value: any) {
    const bindField: string[] = this.componentData.extends.mapField;
    if (bindField) {
      this.mapDataModel[bindField[0]] || (this.mapDataModel[bindField[0]] = {});
      this.mapDataModel[bindField[0]][bindField[1]] = value;
    }
  }

  protected formatObj(value, bindField) {
    if (value && typeof (value) == 'object' && !(value instanceof Array) && !(value instanceof Date)) {
      // 把对象展开
      for (const key of Object.keys(value)) {
        const v = value[key];
        const b = bindField + '.' + key;
        this.formatObj(v, b);
      }
    }
    return this.dataModel[bindField] = value;
  }

  /**
   * 字段的验证
   */
  async validate(params?: {
    objectId?: string;
    dataType: string;
    objectType: 'page' | 'workflow'
  }) {
    // if (this.componentData.readonly) {
    //   return true;
    // }
    if (this.componentData.invalid) {
      return true;
    }
    if (this.componentData.tplInvalid) {
      return true;
    }
    // if (this.componentData.disabled) {
    //   return true;
    // }
    const validations = this.componentData.validations;
    if (Array.isArray(validations) && validations.length) {
      let fieldError: any;
      let value = this.bindData;
      for (const validation of validations) {
        const type = validation.type;
        const fn = this.validatorFns[type];
        // tslint:disable-next-line: max-line-length
        let result: any;
        if (fn) {
          if (this.componentData.extends && this.componentData.extends.multiple && !isNaN(value)) {
            value = value / this.componentData.extends.multiple;
          }
          if (type === 'unique') {
            if (value) {
              const extra = {};
              extra[this.componentData.bindField] = value;
              params = {
                ...params,
                ...extra
              };
              result = await fn(params as any);
            }
          } else {
            result = fn(value, validation as any);
          }
        }
        if (result) {
          fieldError = {
            errors: result,
            inValid: true,
            identifyId: this.componentData.identifyId,
            name: this.componentData.labelText,
            value
          };
          break;
        }
      }
      const errors = this.engineService.fieldErrors;
      if (fieldError) {
        if (errors && errors.length) {
          const index = errors.findIndex(item => item.identifyId === fieldError.identifyId);
          if (index > -1) {
            errors[index] = fieldError;
          } else {
            errors.push(fieldError);
          }
        } else {
          this.engineService.fieldErrors = [fieldError];
        }
      } else {
        if (errors && errors.length) {
          const index = errors.findIndex(item => item.identifyId === this.componentData.identifyId);
          if (index > -1) {
            errors.splice(index, 1);
          }
        }
      }
    }
    if (this.expandedValidation) {
      this.expandedValidation();
    }
  }

  /**
   * 获取指定组件的错误信息
   * @param identifyId 组件的uuid
   */
  getComponentError(identifyId: string) {
    const errors = this.engineService.fieldErrors;
    if (errors) {
      return errors.find(item => item.identifyId === identifyId);
    }
    return null;
  }

  setAuthorityData(): ZeprideAuthorityData {
    if (!this.permitConfig || !this.permitConfig.length) {
      return;
    }
    this.zeprideAuthorityData = {
      refObjectId: this.componentData.tmpComItemId,
      permitConfigs: this.permitConfig,
      target: this.componentData
    };
    return this.zeprideAuthorityData;
  }
}
